/**
 * Git集成工具
 * 提供Git操作所需的功能：提交、回滚、清理等
 */

const { execSync } = require('child_process');

/**
 * 执行Git命令
 * @param {string} command Git命令
 * @param {Object} options 选项
 * @returns {Object} 执行结果
 */
function execGitCommand(command, options = {}) {
    const {
        throwOnError = true,
        silent = false,
        encoding = 'utf8'
    } = options;

    try {
        const fullCommand = `git ${command}`;

        if (!silent) {
            console.log(`🔧 执行Git命令: ${fullCommand}`);
        }

        const output = execSync(fullCommand, {
            encoding: encoding,
            stdio: silent ? 'pipe' : 'inherit'
        });

        return {
            success: true,
            output: output,
            command: fullCommand
        };

    } catch (error) {
        const result = {
            success: false,
            output: error.stdout || '',
            error: error.message,
            command: `git ${command}`,
            exitCode: error.status
        };

        if (throwOnError) {
            throw new Error(`Git命令执行失败: ${error.message}`);
        }

        return result;
    }
}

/**
 * 检查Git仓库状态
 * @returns {Object} 仓库状态信息
 */
function getGitStatus() {
    try {
        // 检查是否在Git仓库中
        const revParse = execGitCommand('rev-parse --git-dir', { silent: true, throwOnError: false });
        if (!revParse.success) {
            return {
                isGitRepo: false,
                error: '当前目录不是Git仓库'
            };
        }

        // 获取状态信息
        const statusResult = execGitCommand('status --porcelain', { silent: true });
        const branchResult = execGitCommand('branch --show-current', { silent: true });
        const commitResult = execGitCommand('log -1 --format=%H', { silent: true });

        const statusLines = statusResult.output.trim().split('\n').filter(line => line.trim());
        const changes = {
            modified: [],
            added: [],
            deleted: [],
            untracked: []
        };

        statusLines.forEach(line => {
            const statusCode = line.substring(0, 2);
            const filePath = line.substring(3);

            switch (statusCode) {
                case ' M':
                case ' M':
                    changes.modified.push(filePath);
                    break;
                case 'A ':
                case ' M':
                    changes.added.push(filePath);
                    break;
                case 'D ':
                case ' D':
                    changes.deleted.push(filePath);
                    break;
                case '??':
                    changes.untracked.push(filePath);
                    break;
            }
        });

        return {
            isGitRepo: true,
            branch: branchResult.output.trim(),
            lastCommit: commitResult.output.trim(),
            hasChanges: statusLines.length > 0,
            changes: changes,
            isClean: statusLines.length === 0
        };

    } catch (error) {
        return {
            isGitRepo: false,
            error: error.message
        };
    }
}

/**
 * 添加所有更改到暂存区
 * @returns {Object} 执行结果
 */
function addAll() {
    return execGitCommand('add .');
}

/**
 * 提交更改
 * @param {string} message 提交信息
 * @param {Object} options 选项
 * @returns {Object} 执行结果
 */
function commit(message, options = {}) {
    const { allowEmpty = false } = options;

    if (!message || message.trim() === '') {
        throw new Error('提交信息不能为空');
    }

    let command = `commit -m "${message}"`;
    if (allowEmpty) {
        command += ' --allow-empty';
    }

    return execGitCommand(command);
}

/**
 * 添加并提交所有更改
 * @param {string} message 提交信息
 * @param {Object} options 选项
 * @returns {Object} 执行结果
 */
function addAndCommit(message, options = {}) {
    console.log(`📝 准备提交更改: ${message}`);

    // 检查是否有更改需要提交
    const status = getGitStatus();
    if (status.isClean && !options.allowEmpty) {
        console.log('✅ 没有需要提交的更改');
        return { success: true, message: '没有需要提交的更改' };
    }

    // 添加所有更改
    addAll();

    // 提交
    const commitResult = commit(message, options);

    if (commitResult.success) {
        console.log('✅ 提交成功');

        // 获取新的提交哈希
        const newCommit = execGitCommand('log -1 --format=%H', { silent: true });
        commitResult.commit = newCommit.output.trim();
    }

    return commitResult;
}

/**
 * 回滚到上一个提交
 * @param {Object} options 选项
 * @returns {Object} 执行结果
 */
function rollback(options = {}) {
    const {
        target = 'HEAD~1',     // 回滚目标
        hard = true,           // 是否使用--hard
        clean = false          // 是否清理未跟踪文件
    } = options;

    console.log(`⏪ 回滚到: ${target}`);

    // 重置到指定提交
    const resetCommand = `reset ${hard ? '--hard' : '--soft'} ${target}`;
    const resetResult = execGitCommand(resetCommand);

    if (resetResult.success && clean) {
        console.log('🧹 清理未跟踪文件...');
        // 清理未跟踪的文件和目录
        execGitCommand('clean -fd');
    }

    return resetResult;
}

/**
 * 清理工作目录
 * @param {Object} options 选项
 * @returns {Object} 执行结果
 */
function cleanWorkingDirectory(options = {}) {
    const {
        resetFirst = true,     // 是否先重置
        cleanUntracked = true, // 是否清理未跟踪文件
        target = 'HEAD~1'      // 重置目标
    } = options;

    console.log('🧹 清理工作目录...');

    const results = [];

    try {
        if (resetFirst) {
            // 重置到上一个提交
            const resetResult = rollback({ target: target, hard: false });
            results.push({ action: 'reset', ...resetResult });
        }

        if (cleanUntracked) {
            // 清理未跟踪的文件
            const cleanResult = execGitCommand('clean -fd', { silent: true });
            results.push({ action: 'clean', ...cleanResult });
        }

        // 丢弃工作区的更改
        const discardResult = execGitCommand('checkout -- .', { silent: true });
        results.push({ action: 'discard', ...discardResult });

        return {
            success: true,
            results: results,
            message: '工作目录清理完成'
        };

    } catch (error) {
        return {
            success: false,
            error: error.message,
            results: results
        };
    }
}

/**
 * 获取最近的提交历史
 * @param {number} count 提交数量
 * @returns {Array} 提交历史
 */
function getRecentCommits(count = 5) {
    try {
        const result = execGitCommand(`log -${count} --format="%H|%s|%ai|%an"`, { silent: true });
        const lines = result.output.trim().split('\n');

        return lines.map(line => {
            const [hash, subject, date, author] = line.split('|');
            return {
                hash: hash,
                subject: subject,
                date: new Date(date),
                author: author
            };
        });

    } catch (error) {
        console.error('获取提交历史失败:', error.message);
        return [];
    }
}

/**
 * 检查是否有未提交的更改
 * @returns {boolean} 是否有未提交的更改
 */
function hasUncommittedChanges() {
    const status = getGitStatus();
    return !status.isClean;
}

/**
 * 创建备份分支
 * @param {string} branchName 分支名称
 * @returns {Object} 执行结果
 */
function createBackupBranch(branchName = null) {
    if (!branchName) {
        const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
        branchName = `backup-${timestamp}`;
    }

    return execGitCommand(`checkout -b ${branchName}`);
}

// 如果直接运行此脚本，显示Git状态信息
if (require.main === module) {
    console.log('📊 Git仓库状态检查');
    console.log('='.repeat(30));

    const status = getGitStatus();

    if (!status.isGitRepo) {
        console.log('❌ 当前目录不是Git仓库');
        process.exit(1);
    }

    console.log(`分支: ${status.branch}`);
    console.log(`最新提交: ${status.lastCommit.substring(0, 8)}`);
    console.log(`状态: ${status.isClean ? '✅ 干净' : '⚠️  有未提交更改'}`);

    if (status.hasChanges) {
        console.log('\n📝 更改统计:');
        console.log(`修改: ${status.changes.modified.length} 个文件`);
        console.log(`新增: ${status.changes.added.length} 个文件`);
        console.log(`删除: ${status.changes.deleted.length} 个文件`);
        console.log(`未跟踪: ${status.changes.untracked.length} 个文件`);

        if (status.changes.modified.length > 0) {
            console.log('\n修改的文件:');
            status.changes.modified.forEach(file => console.log(`  - ${file}`));
        }
    }

    console.log('\n📜 最近提交:');
    const recentCommits = getRecentCommits(3);
    recentCommits.forEach(commit => {
        console.log(`  ${commit.hash.substring(0, 8)} - ${commit.subject} (${commit.date.toLocaleDateString()})`);
    });
}

module.exports = {
    execGitCommand,
    getGitStatus,
    addAll,
    commit,
    addAndCommit,
    rollback,
    cleanWorkingDirectory,
    getRecentCommits,
    hasUncommittedChanges,
    createBackupBranch
};